package com.engine4cloud.tdf.supervision.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.engine4cloud.tdf.common.data.web.query.Queries;
import com.engine4cloud.tdf.common.security.service.TdfUser;
import com.engine4cloud.tdf.supervision.convert.JzdxFileConvert;
import com.engine4cloud.tdf.supervision.dto.JzdxFileDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxFileQueryDTO;
import com.engine4cloud.tdf.supervision.dto.result.JzdxFileResultDTO;
import com.engine4cloud.tdf.supervision.entity.JzdxFileEntity;
import com.engine4cloud.tdf.supervision.mapper.JzdxFileMapper;
import com.engine4cloud.tdf.supervision.service.JzdxFileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 监督管理-文件表
 *
 * @author wenjie
 * @date 2024-03-06 10:25:56
 */
@Slf4j
@Service
public class JzdxFileServiceImpl extends ServiceImpl<JzdxFileMapper, JzdxFileEntity> implements JzdxFileService {
    @Override
    public List<JzdxFileResultDTO> findList(JzdxFileQueryDTO dto) {
        return list(wrapperList(dto)).stream().map(JzdxFileConvert.INSTANCE::convert).toList();
    }

    /**
     * 保存文件，保存时需要注意设置 矫正对编号或调查评估编号
     *
     * @param dto      参数
     * @param fileList 文件列表
     * @param user     登录人
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSaveFile(JzdxFileQueryDTO dto, List<JzdxFileDTO> fileList, TdfUser user) {
        this.saveBatch(JzdxFileConvert.INSTANCE.createList(dto, fileList, user));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateFile(JzdxFileQueryDTO dto, List<JzdxFileDTO> fileList, TdfUser user) {
        //查询已经存在的
        List<JzdxFileResultDTO> existedList = this.findList(dto);

        //查询需要保存的
        List<JzdxFileEntity> preSaveFileList = this.preSaveFileList(dto, fileList, user);
        if (CollectionUtils.isNotEmpty(preSaveFileList)) {
            this.saveBatch(preSaveFileList);
        }

        //查询需要删除的
        List<Long> preDeleteFileList = this.preDeleteFileList(existedList, fileList);
        if (CollectionUtils.isNotEmpty(preDeleteFileList)) {
            this.removeBatchByIds(preDeleteFileList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateDetailFile(JzdxFileQueryDTO dto, List<JzdxFileDTO> fileList, TdfUser user) {
        //查询已经存在的
        List<JzdxFileResultDTO> existedList = this.findList(dto);

        //查询需要保存的
        List<JzdxFileEntity> preSaveFileList = this.preSaveFileList(dto, fileList, user);
        if (CollectionUtils.isNotEmpty(preSaveFileList)) {
            this.saveBatch(preSaveFileList);
        }

        //查询需要删除的
        List<Long> preDeleteFileList = this.preDeleteFileList(existedList, fileList);
        if (CollectionUtils.isNotEmpty(preDeleteFileList)) {
            this.removeBatchByIds(preDeleteFileList);
        }

        //查询需要修改的
        List<JzdxFileResultDTO> preUpdateFileList = this.preUpdateFileList(existedList, fileList);
        if (CollectionUtils.isNotEmpty(preUpdateFileList)) {
            this.updateBatchById(JzdxFileConvert.INSTANCE.convert(preUpdateFileList));
        }
    }

    private List<JzdxFileEntity> preSaveFileList(JzdxFileQueryDTO dto, List<JzdxFileDTO> fileList, TdfUser user) {
        if (CollectionUtils.isEmpty(fileList)) {
            return Collections.emptyList();
        }

        return fileList.stream().filter(file -> Objects.isNull(file.getId())).map(file ->
                JzdxFileConvert.INSTANCE.create(dto.getRybh(), dto.getDcpgbh(), dto.getLcbh(), dto.getFileType(), file, user)).toList();
    }

    private List<Long> preDeleteFileList(List<JzdxFileResultDTO> existedList, List<JzdxFileDTO> modelFileList) {
        if (CollectionUtils.isEmpty(existedList)) {
            return Collections.emptyList();
        }

        Map<Long, JzdxFileDTO> modelFileMap = modelFileList.stream().filter(model -> Objects.nonNull(model.getId())).collect(Collectors.toMap(JzdxFileDTO::getId, Function.identity(), (v1, v2) -> v1));
        return existedList.stream().map(JzdxFileResultDTO::getId).filter(id -> !modelFileMap.containsKey(id)).toList();
    }

    private List<JzdxFileResultDTO> preUpdateFileList(List<JzdxFileResultDTO> existedList, List<JzdxFileDTO> modelFileList) {
        if (CollectionUtils.isEmpty(existedList) || CollectionUtils.isEmpty(modelFileList)) {
            return Collections.emptyList();
        }

        List<JzdxFileResultDTO> preUpdateFileList = new ArrayList<>();

        Map<Long, JzdxFileResultDTO> existedMap = existedList.stream().collect(Collectors.toMap(JzdxFileResultDTO::getId, v -> v));
        for (JzdxFileDTO file : modelFileList) {
            if (Objects.nonNull(file.getId()) && existedMap.containsKey(file.getId())) {
                JzdxFileResultDTO exist = existedMap.get(file.getId());
                if (StringUtils.isNotEmpty(file.getName()) && !Objects.equals(file.getName(), exist.getName())) {
                    exist.setName(file.getName());
                    preUpdateFileList.add(exist);
                }
            }
        }

        return preUpdateFileList;
    }

    private LambdaQueryWrapper<JzdxFileEntity> wrapperList(JzdxFileQueryDTO query) {
        LambdaQueryWrapper<JzdxFileEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(JzdxFileEntity::getId, v));
        Queries.accept(query.getDcpgbh(), v -> wrapper.eq(JzdxFileEntity::getDcpgbh, v));
        Queries.accept(query.getRybh(), v -> wrapper.eq(JzdxFileEntity::getRybh, v));
        Queries.accept(query.getLcbh(), v -> wrapper.eq(JzdxFileEntity::getLcbh, v));
        Queries.accept(query.getFileType(), v -> wrapper.eq(JzdxFileEntity::getFileType, v));
        Queries.accept(query.getCodeList(), v -> wrapper.in(JzdxFileEntity::getDcpgbh, v));
        return wrapper;
    }
}